<template>
    <view class="_tab-box" :style="{ fontSize: defaultConfig.fontSize + 'rpx', color: defaultConfig.color }">
        <scroll-view id="_scroll" :scroll-x="true" class="scroll-view-h" scroll-with-animation :scroll-left="slider.scrollLeft" ref="scrollViewRef">
            <view class="_scroll-content">
                <view class="_tab-item-box" :class="[defaultConfig.itemWidth ? '_clamp' : '_flex']">
                    <block v-for="(item, index) in tabList" :key="index">
                        <view class="_item" :id="'_tab_' + index" :class="{ _active: tagIndex === index }" :style="{ color: tagIndex == index ? defaultConfig.activeColor : defaultConfig.color, width: defaultConfig.itemWidth ? defaultConfig.itemWidth + 'rpx' : '' }" @click="tabClick(index, item.id)">
                            <view class="url-img">
                                <view class="class-img"><img class="img" :src="item.activityImg" /></view>
                                <view class="title">{{ item[defaultConfig.key] || item }}</view>
                            </view>
                        </view>
                    </block>
                </view>
                <view
                    v-if="defaultConfig.showUnderLine"
                    class="_underline"
                    :style="{
                        transform: 'translateX(' + slider.left + 'px)',
                        width: slider.width + 'px',
                        height: defaultConfig.underLineHeight + 'rpx',
                        backgroundColor: defaultConfig.underLineColor
                    }" />
            </view>
        </scroll-view>
    </view>
</template>

<script setup>
import { ref, reactive, watch, onMounted, nextTick, getCurrentInstance } from 'vue';

const { proxy } = getCurrentInstance();

const props = defineProps({
    tabData: {
        type: Array,
        default: () => []
    },
    activeIndex: {
        type: Number,
        default: 0
    },
    config: {
        type: Object,
        default: () => ({})
    }
});

const emit = defineEmits(['tabClick']);

const tabList = ref([]);
const tagIndex = ref(0);
const slider = reactive({
    left: 0,
    width: 0,
    scrollLeft: 0
});
const scorll = reactive({});
const defaultConfig = reactive({
    key: 'activityName', //默认key(如果你的是name或者label传name或者label)
    fontSize: 26, //默认字体大小
    color: '#313131', //默认颜色

    activeColor: '#e54d42', //选中字体颜色
    itemWidth: 0,
    underLinePadding: 10,
    underLineWidth: 0,
    underLineHeight: 4,
    underLineColor: '#e54d42', //下划线颜色
    showUnderLine: true //是否开启下划线
});

const scrollViewRef = ref(null);

const updateData = () => {
    let data = [];
    if (typeof props.tabData[0] === 'string') {
        props.tabData.forEach((item, index) => {
            data.push({
                name: item.activityName,
                img: item.activityImg
            });
        });
        defaultConfig.key = defaultConfig.key;
    } else {
        data = JSON.parse(JSON.stringify(props.tabData));
    }
    tabList.value = data;
};

const updateConfig = () => {
    Object.assign(defaultConfig, props.config);
};

const calcScrollPosition = () => {
    const query = uni.createSelectorQuery().in(proxy);

    query
        .select('#_scroll')
        .boundingClientRect(res => {
            scorll.value = res;
            updateTabWidth();
        })
        .exec();
};

const updateTabWidth = (index = 0) => {
    let data = tabList.value;

    if (data.length === 0) return false;

    const query = uni.createSelectorQuery().in(proxy);

    query
        .select('#_tab_' + index)
        .boundingClientRect(res => {
            data[index]._slider = {
                width: res.width,
                left: res.left,
                scrollLeft: res.left - (data[index - 1] ? data[index - 1]._slider.width : 0)
            };

            if (tagIndex.value === index) {
                tabToIndex(tagIndex.value);
            }

            index++;
            if (data.length > index) {
                updateTabWidth(index);
            }
        })
        .exec();
};

const tabToIndex = index => {
    let _slider = tabList.value[index]._slider;

    if (!_slider) {
        // 如果 _slider 未定义，重新计算
        updateTabWidth(index);
        _slider = tabList.value[index]._slider;
    }

    let width = uni.upx2px(defaultConfig.underLineWidth);

    if (!width) {
        if (defaultConfig.itemWidth) {
            width = uni.upx2px(defaultConfig.itemWidth);
        } else {
            width = tabList.value[index][defaultConfig.key].length * uni.upx2px(defaultConfig.fontSize);
        }
        width += uni.upx2px(defaultConfig.underLinePadding) * 2;
    }

    let scorll_left = scorll.value.left || 0;

    slider.left = _slider.left - scorll_left + (_slider.width - width) / 2;
    slider.width = width;
    slider.scrollLeft = _slider.scrollLeft - scorll_left;

    // 更新 scroll-view 的 scroll-left 属性
    nextTick(() => {
        if (scrollViewRef.value) {
            scrollViewRef.value.scrollLeft = slider.scrollLeft;
        }
    });
};

const tabClick = (index, id) => {
    tagIndex.value = index;
    tabToIndex(index);
    emit('tabClick', id);
};

watch(
    () => props.tabData,
    value => {
        updateData();
        nextTick(() => {
            updateTabWidth();
        });
    }
);

watch(
    () => props.config,
    value => {
        updateConfig();
    }
);

onMounted(() => {
    updateConfig();
    updateData();
    tagIndex.value = props.activeIndex;

    nextTick(() => {
        calcScrollPosition();
    });
});
</script>

<style lang="scss" scoped>
._tab-box {
    width: 100%;
    display: flex;
    font-size: 26rpx;
    position: relative;
    z-index: 0;
    .scroll-view-h {
        white-space: nowrap;
        width: 100%;
        height: 100%;
        box-sizing: border-box;
        ._scroll-content {
            width: 100%;
            height: 100%;
            position: relative;

            ._tab-item-box {
                height: 100%;
                &._flex {
                    display: flex;
                    ._item {
                        flex: 1;
                    }
                }
                &._clamp {
                    ._item {
                        overflow: hidden;
                        text-overflow: ellipsis;
                        white-space: nowrap;
                    }
                }

                ._item {
                    height: 100%;
                    display: inline-block;
                    text-align: center;
                    padding: 0 20rpx;
                    position: relative;
                    text-align: center;
                    color: #363a44;
                    &._active {
                        .url-img {
                            .class-img {
                                border: 4rpx solid #0e5dd4;
                            }
                            .title {
                                color: #fff;
                                // width: 88rpx;
                                padding: 0 20rpx;
                                height: 40rpx;
                                background: #0e5dd4;
                                border-radius: 20rpx;
                            }
                        }
                    }
                }
            }
            ._underline {
                height: 4rpx;
                background-color: #e54d42;
                border-radius: 6rpx;
                transition: 0.5s;
                position: absolute;
                bottom: 0;
            }
        }
    }
}
.url-img {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    .img {
        width: 108rpx;
        height: 108rpx;
    }
}
.class-img {
    display: flex;
    justify-content: center;
    align-items: center;
    overflow: hidden;
    width: 108rpx;
    height: 108rpx;
    border-radius: 108rpx;
    border: 4rpx solid #fff;
    box-shadow: 0rpx 4rpx 16rpx 0rpx rgba(0, 0, 0, 0.1);
    background: linear-gradient(180deg, #c5c1e5 0%, #dbd9ec 100%);
}
.title {
    margin-top: 15rpx;
}
</style>
